﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace ATest.Bll
{
    public partial class Question : BaseItem, Interfaces.IValidate
    {
        partial void OnCreated()
        {
            this._Text = XElement.Parse("<xml/>");
        }

        partial void OnValidate(System.Data.Linq.ChangeAction action)
        {
            if (action == System.Data.Linq.ChangeAction.Insert || action == System.Data.Linq.ChangeAction.Update)
            {
                if (action == System.Data.Linq.ChangeAction.Insert)
                {
                    this.UTCCreated = this.UTCLastUpdated = DateTime.UtcNow;
                    this._CreatedBy = this._LastUpdatedBy = GetLoginName();
                }
                else
                {
                    this.UTCLastUpdated = DateTime.UtcNow;
                    this._LastUpdatedBy = GetLoginName();
                }

                if (!IsValid)
                {
                    throw new Errors.ValidationException("Rule Violations Prevented Saving");
                }
            }
        }

        public bool IsValid
        {
            get { return GetRuleViolations().Count() == 0; }
        }

        public IEnumerable<RuleViolation> GetRuleViolations()
        {
            if (string.IsNullOrEmpty(Name))
                yield return new RuleViolation("Name is required", "Name");
            if (this.Text == null || string.IsNullOrEmpty(Text.Value))
                yield return new RuleViolation("Text must be set", "Text");
            yield break;
        }

        public void SetText(string text)
        {
            this._Text = XElement.Parse(string.Format("<xml>{0}</xml>", text));
        }

        public string GetText()
        {
            StringBuilder innerXml = new StringBuilder();
            this.Text.Nodes().ToList().ForEach(node => innerXml.Append(node.ToString()));
            return innerXml.ToString();
        }

        public string GetTextSummary(int length)
        {
            StringBuilder xml = new StringBuilder();
            System.Xml.XmlReader reader = Text.CreateReader();
            int currentLength = 0;
            var nodesAdded = new List<string>();
            reader.Read();//skip xml node
            while (reader.Read())
            {
                if (reader.NodeType == System.Xml.XmlNodeType.Text)
                {
                    var tmp = reader.Value;
                    if (currentLength + tmp.Length < length)
                    {
                        xml.Append(tmp);
                        currentLength += tmp.Length;
                    }
                    else if(currentLength < length)
                    {
                        tmp = tmp.Substring(0, length - currentLength);
                        xml.Append(tmp);
                        currentLength += tmp.Length;
                    }
                }
                else if (reader.NodeType == System.Xml.XmlNodeType.Element)
                {
                    if (currentLength < length)
                    {
                        xml.Append("<");
                        xml.Append(reader.Name);
                        nodesAdded.Add(reader.Name);
                        if (reader.HasAttributes)
                        {
                            while (reader.MoveToNextAttribute())
                            {
                                xml.AppendFormat(" {0}=\"{1}\"", reader.Name, reader.Value);
                            }
                        }
                        xml.Append(">");
                    }
                }
                else if (reader.NodeType == System.Xml.XmlNodeType.EndElement)
                {
                    if (currentLength < length && nodesAdded.Count > 0)
                    {
                        xml.AppendFormat("</{0}>", reader.Name);
                        nodesAdded.RemoveAt(nodesAdded.Count - 1);
                    }
                }
            }
            nodesAdded.Reverse();
            foreach (string node in nodesAdded)
            {
                xml.AppendFormat("</{0}>", node);
            }

            //var elems = this.Text.Nodes().ToList();
            //foreach(var elem in elems)
            //{
            //    if(elem.NodeType == System.Xml.XmlNodeType.Text)
            //    {
            //        xml.Append(elem.ToString());
            //    }
            //}*/
            return xml.ToString();
            //AddText(elems, xml, "");
            //return xml.ToString();
        }

        private void AddText(List<XElement> elems, StringBuilder xmlOut, string length)
        {
            foreach (var elem in elems)
            {
                if (elem.HasElements)
                {
                    AddText(elem.Elements().ToList(), xmlOut, length);
                }
                else if (!elem.IsEmpty)
                {
                    xmlOut.Append(elem.ToString());
                }
            }
        }

        public DateTime Created
        {
            get
            {
                return UTCCreated.ToLocalTime();
            }
        }

        public DateTime LastUpdated
        {
            get
            {
                return UTCLastUpdated.ToLocalTime();
            }
        }
    }
}
